package org.xxpay.pay.channel.yunsfpay;

import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Service;
import org.xxpay.core.common.constant.MchConstant;
import org.xxpay.core.common.constant.PayConstant;
import org.xxpay.core.common.util.MyLog;
import org.xxpay.core.entity.PayOrder;
import org.xxpay.pay.channel.BasePayNotify;
import org.xxpay.pay.channel.yunsfpay.util.PayUtils;

import javax.servlet.http.HttpServletRequest;
import java.util.Map;

/**
 * @Description 云闪付回调接口
 * @author hjj
 * @email  1977947499@qq.com
 * @EditDate  2019年1月18日 上午11:19:37
 *
 */
@Service
public class YunsfpayPayNotifyService extends BasePayNotify {
    private static final MyLog _log = MyLog.getLog(YunsfpayPayNotifyService.class);

    @Override
    public String getChannelName() {
        return YunsfpayConfig.CHANNEL_NAME;
    }

    @Override
    public JSONObject doNotify(Object notifyData) {
        String logPrefix = "【处理Yunsfpay支付回调】";
        _log.info("====== 开始处理Yunsfpay支付回调通知 ======");
        HttpServletRequest req = (HttpServletRequest) notifyData;
        JSONObject retObj = new JSONObject();
        String respString = PayConstant.RETURN_VALUE_FAIL;
        try {
            req.setCharacterEncoding("utf-8");
            JSONObject resJson = new JSONObject();
            for (String name : req.getParameterMap().keySet()) {
                resJson.put(name, req.getParameter(name));
            }
            _log.info("Yunsfpay异步通知内容：{}", resJson);
            // 将响应结果json字换串转map
            Map<String, Object> resMap = PayUtils.parseJSON2Map(resJson.toJSONString());
            _log.info("Yunsfpay异步通知内容resMap：{}", resMap);
            // 查询payOrder记录
            String payOrderId = resMap.get("mark").toString();
            PayOrder payOrder = commonService.payOrderService.findByPayOrderId(payOrderId);
            YunsfpayConfig yunsfpayConfig = new YunsfpayConfig(getPayParam(payOrder));
            // 验证通知内容
            if (!verifySignature(yunsfpayConfig.getMchId(),yunsfpayConfig.getKey(),resMap)) {
                _log.info("Yunsfpay异步通知验签失败");
                retObj.put(PayConstant.RESPONSE_RESULT, respString);
                return retObj;
            }
            _log.info("Yunsfpay异步通知：验签成功");
            // 设置平台订单号
            payOrder.setPayOrderId(payOrderId);
            // 设置渠道订单号
            payOrder.setChannelOrderNo(resJson.getString("no"));
            int updatePayOrderRows = commonService.payOrderService.updateStatus4Success(payOrder.getPayOrderId());
            if (updatePayOrderRows != 1) {
                _log.error("{}更新支付状态失败,将payOrderId={},更新payStatus={}失败", logPrefix, payOrder.getPayOrderId(),PayConstant.PAY_STATUS_SUCCESS);
                retObj.put(PayConstant.RESPONSE_RESULT, "处理订单失败");
                return retObj;
            }
            _log.error("{}更新支付状态成功,将payOrderId={},更新payStatus={}成功", logPrefix, payOrder.getPayOrderId(),PayConstant.PAY_STATUS_SUCCESS);
            payOrder.setStatus(PayConstant.PAY_STATUS_SUCCESS);
            // 业务系统后端通知
            baseNotify4MchPay.doNotify(payOrder, true);
            _log.info("====== 完成处理Yunsfpay支付回调通知 ======");
            // 返回上游信息
            respString = "success";
        } catch (Exception e) {
            _log.error(e, logPrefix + "处理异常");
            retObj.put(PayConstant.RESPONSE_RESULT, respString);
            return retObj;
        }
        retObj.put(PayConstant.RESPONSE_RESULT, respString);
        return retObj;
    }

    /**
     * 签名校验
     * @return
     */
    private boolean verifySignature(String merId,String signKey,Map<String,Object> map){
        String signStr = map.get("sign").toString();
        _log.info("返回的sign值：{}",signStr);
        map.remove("sign");
        // 用户id/商户号/设备号
        map.put("userids",merId);
        // 商户key
        map.put("signkey",signKey);
        String signStr1 = PayUtils.getYunsfSign(map);
        _log.info("待签名的map===>>>：{}",map);
        _log.info("自己的sign值：{}",signStr1);
        if(signStr.equals(signStr1) || signStr == signStr1){
            return true;
        }
        return false;
    }

}
